package com.hzit.alipay.front.controller;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.common.models.AlipayTradeCloseResponse;
import com.alipay.easysdk.payment.common.models.AlipayTradeQueryResponse;
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
import com.hzit.alipay.front.config.AlipayFrontConfig;
import com.hzit.loan.pay.commonApi.enums.PayStatusEnum;
import com.hzit.loan.pay.commonApi.resp.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;

/**
 * 对接支付宝
 */
@RestController
@RequestMapping("/alipayFront")
public class AlipayFrontController {


    @Autowired
    private AlipayFrontConfig alipayFrontConfig;

    private Logger logger = LoggerFactory.getLogger(AlipayFrontController.class);



    /**
     * 支付宝扫码支付
     * @param subject
     * @param paySeiralNo
     * @param mchOrderAmt
     * @return 二维码地址
     */
    @RequestMapping("/qrCodePay")
    public RespVo<PayResultData> qrCodePay(@RequestParam("subject")String subject,
                            @RequestParam("paySeiralNo")String paySeiralNo,
                            @RequestParam("mchOrderAmt")String mchOrderAmt){

        /************************根据支付宝开发文档开发******************************************/


        //初始化支付宝环境
        ininConfig();

        if(StringUtils.isEmpty(subject)){
            return RespVo.getFailReturn("subject不能为空");
        }

        if(StringUtils.isEmpty(paySeiralNo)){
            return RespVo.getFailReturn("PaySerialNo不能为空");
        }
        if(StringUtils.isEmpty(mchOrderAmt)){
            return RespVo.getFailReturn("Amount不能为空");
        }

        try {
            AlipayTradePrecreateResponse response = Factory.Payment.FaceToFace()
                    .preCreate(subject,paySeiralNo,mchOrderAmt);

            //解析
            if(!"10000".equals(response.getCode())){
                logger.info("支付流水号{}:调用支付宝接口失败：{}",paySeiralNo,response.getMsg());
                return RespVo.getFailReturn(response.getMsg());
            }

            RespVo<PayResultData> respVo = new RespVo<PayResultData>();
            String qrCodeUrl = response.getQrCode();
            logger.info("qrCodeUrl = " + qrCodeUrl);

            respVo.setCode(0);
            respVo.setMsg("处理成功");

            PayResultData payResultData = new PayResultData();
            payResultData.setPayUrl(qrCodeUrl);

            respVo.setData(payResultData);
            return respVo;

        } catch (Exception e) {
            logger.error("Exception",e);
            return RespVo.getFailReturn(e.getMessage());
        }
    }


    /**
     * 支付宝支付查询接口
     * @param paySeiralNo
     * @return
     */
    @RequestMapping("/query")
    public RespVo<PayNotifyData> payQuery(@RequestParam("paySeiralNo")String paySeiralNo) {

        logger.info("收到支付宝支付查询接口请求，参数paySeiralNo:{}",paySeiralNo);

        if(StringUtils.isEmpty(paySeiralNo)){
            return RespVo.getFailReturn("PaySerialNo不能为空");
        }

        //调用支付宝查询接口
        ininConfig();
        AlipayTradeQueryResponse alipayTradeQueryResponse = null;
        try {
            alipayTradeQueryResponse = Factory.Payment.Common().query(paySeiralNo);
        } catch (Exception e) {
            logger.error("Exception",e);
        }

        if (ObjectUtils.isEmpty(alipayTradeQueryResponse)){
            logger.info("流水号：{},调用支付宝查询接口异常", paySeiralNo);
            return RespVo.getFailReturn("调用支付宝查询接口异常");
        }

        if (!"10000".equals(alipayTradeQueryResponse.getCode())){
            logger.info("流水号：{},查询失败:{}", paySeiralNo,alipayTradeQueryResponse.getMsg());
            return RespVo.getFailReturn(alipayTradeQueryResponse.getMsg());
        }

        //封装对象返回

        RespVo<PayNotifyData> respVo = new RespVo<PayNotifyData>();
        PayNotifyData payNotifyData = new PayNotifyData();

        if("TRADE_FINISHED".equals(alipayTradeQueryResponse.getTradeStatus())
                || "TRADE_SUCCESS".equals(alipayTradeQueryResponse.getTradeStatus())){

            //封装返回给
            payNotifyData.setTradeStatus(String.valueOf(PayStatusEnum.SUCCESS.getCode()));
            payNotifyData.setStatusDesc(PayStatusEnum.SUCCESS.getDesc());


        } else if("TRADE_CLOSED".equals(alipayTradeQueryResponse.getTradeStatus())){

            payNotifyData.setTradeStatus(String.valueOf(PayStatusEnum.FAIL.getCode()));
            payNotifyData.setStatusDesc(PayStatusEnum.FAIL.getDesc());

        }else{
            payNotifyData.setTradeStatus(String.valueOf(PayStatusEnum.PAY_ING.getCode()));
            payNotifyData.setStatusDesc(PayStatusEnum.PAY_ING.getDesc());

        }

        //TODO 生成签名
        String sing = "";
        payNotifyData.setSign(sing);
        respVo.setData(payNotifyData);
        return respVo;
    }


    /**
     * 支付宝交易关闭接口
     * @param paySeiralNo
     */
    @RequestMapping("/tradeClose")
    public RespVo<TradeCloseRespData> tradeClose(@RequestParam("paySeiralNo")String paySeiralNo){

        logger.info("收到支付宝支付交易关闭请求，参数paySeiralNo:{}",paySeiralNo);

        if(StringUtils.isEmpty(paySeiralNo)){
            return RespVo.getFailReturn("PaySerialNo不能为空");
        }


        try {
            ininConfig();
            AlipayTradeCloseResponse alipayTradeCloseResponse = Factory.Payment.Common().close(paySeiralNo);
            //
            RespVo<TradeCloseRespData> respVo = new RespVo<TradeCloseRespData>();

            TradeCloseRespData tradeCloseRespData = new TradeCloseRespData();

            if("10000".equals(alipayTradeCloseResponse.getCode())){
                tradeCloseRespData.setStatus(String.valueOf(PayStatusEnum.FAIL.getCode()));
                tradeCloseRespData.setDesc("主动关闭订单");
                //继续封装

                respVo.setData(tradeCloseRespData);

                //生成签名

                return respVo;
            }

            tradeCloseRespData.setStatus(String.valueOf(PayStatusEnum.UN_PAY.getCode()));
            //继续封装
            respVo.setData(tradeCloseRespData);

            //生成签名
            return respVo;
        } catch (Exception e) {
            logger.error("Exception",e);
            return RespVo.getFailReturn(e.getMessage());
        }


    }

    /**
     * 支付宝退款接口
     * @param refundSerialNo
     * @param paySeiralNo
     * @param refundAmt
     * @param refundReason
     */
    @RequestMapping("/refund")
    public RespVo<AlipayRefundRespData> refund(@RequestParam("refundSerialNo")String refundSerialNo,
                                               @RequestParam("paySeiralNo")String paySeiralNo,
                                               @RequestParam("refundAmt")String refundAmt,
                                               @RequestParam("refundReason")String refundReason){

        logger.info("收到支付宝支付退款请求，refundSerialNo:{},refundSerialNo：{},refundAmt:{},refundReason:{}",
                refundSerialNo, refundSerialNo,refundAmt,refundReason);

        if(StringUtils.isEmpty(refundSerialNo)){
            return RespVo.getFailReturn("refundSerialNo不能为空");
        }

        if(StringUtils.isEmpty(refundAmt)){
            return RespVo.getFailReturn("refundAmt不能为空");
        }

        if(StringUtils.isEmpty(paySeiralNo)){
            return RespVo.getFailReturn("paySeiralNo不能为空");
        }

        AlipayClient alipayClient = new DefaultAlipayClient(alipayFrontConfig.getAliapyGateWayUrl(),alipayFrontConfig.getAlipayAppId(),
                alipayFrontConfig.getPrivateKey(),"json","GBK",alipayFrontConfig.getAliapyPubKey(),"RSA2");

        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();

        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no",paySeiralNo);
        bizContent.put("refund_amount",refundAmt);
        bizContent.put("refund_reason",refundSerialNo);
        bizContent.put("out_request_no",refundSerialNo);

        request.setBizContent(bizContent.toJSONString());

        try {
            com.alipay.api.response.AlipayTradeRefundResponse response = alipayClient.execute(request);
            if(!"10000".equals(response.getCode())){
                return RespVo.getFailReturn(response.getMsg());
            }

            RespVo<AlipayRefundRespData> respVo = new RespVo<AlipayRefundRespData>();

            AlipayRefundRespData refundRespData = new AlipayRefundRespData();
            if(!"ACQ.TRADE_HAS_SUCCESS".equals(response.getSubCode())){
                logger.info("退款流水号：{}退款失败原因：{}",refundSerialNo,response.getSubMsg());
                respVo.setCode(-1);
                respVo.setMsg("退款失败");
                refundRespData.setSuccess(false);
                refundRespData.setDesc(response.getSubMsg());
                return respVo;
            }
            //TODO 封装参数， 签名

            respVo.setCode(0);
            respVo.setMsg(response.getSubMsg());
            refundRespData.setSuccess(true);
            refundRespData.setDesc("退款成功");
//          refundRespData.setRefundSuccessTime(response.get);
            respVo.setData(refundRespData);

            return respVo;
        } catch (AlipayApiException e) {
            logger.error("AlipayApiException",e);
            return RespVo.getFailReturn(e.getMessage());
        }


    }





    //对账



    private void ininConfig(){

        //设置系统参数
        Config config = new Config();
        config.protocol = "https";
        config.gatewayHost = "openapi.alipaydev.com";
        config.signType = "RSA2";

        config.appId = alipayFrontConfig.getAlipayAppId();

        config.merchantPrivateKey = alipayFrontConfig.getPrivateKey();

        config.alipayPublicKey = alipayFrontConfig.getAliapyPubKey();
        config.notifyUrl = alipayFrontConfig.getNotifyUrl();

        Factory.setOptions(config);
    }


}
